import Tablero
import Damas
import HUnit
import Maybe

-- algunas igualdades necesarias:
instance Eq Tablero where
  (==) t1 t2 = foldr (\pos b -> (contenido pos t1) == (contenido pos t2) && b) True todasLasPosiciones  
--simplemente se fija que coincidan en todas las posiciones
  
instance Eq Movimiento where
  (==) (M p1 d1) (M p2 d2) = p1 == p2 && d1 == d2
  
instance Eq Juego where
  (==) (J turno1 tablero1) (J turno2 tablero2) = turno1 == turno2 && tablero1 == tablero2
  
-- evaluar t para correr todos los tests
t = runTestTT allTests

allTests = test [ 
	"contenido" ~: testsContenido,
	"poner" ~: testsPoner,
	"mover" ~: testsMover,
	"movimientosPosibles" ~: testsMovimientosPosibles,
	"cantidad de fichas" ~: testsCantidadDeFichas,
	"mejor movimiento" ~: testsMejorMovimiento
	]

testsContenido = test [ 
	 Just _b 	~=? contenido a_1 tableroInicial, 
	 Nothing 	~=? contenido a_2 tableroInicial,
	 Nothing 	~=? contenido a_2 vacio, 
	 Just _n 	~=? contenido a_7 tableroInicial
	 ]
	
testsPoner = test [ 
	 Just _b	~=? contenido a_1 (poner a_1 _b vacio),
	 Nothing 	~=? contenido a_1 (sacar a_1 (poner a_1 _n vacio))
	 ]

jInicial = J Blanca tableroInicial

juego2 = (mover (M b_4 TR) (fromJust (mover (M d_6 BL) (fromJust (mover (M a_3 TR) jInicial)))))
juego3 = mover (M c_3 TL) (fromJust (mover (M a_3 TR) jInicial))
tablero4 = (poner f_2 _b (poner h_2 _n (poner b_8 _n (poner e_7 _b vacio))))
juego4 = (J Blanca tablero4)
juego5 = (J Negra tablero4)

testsMover = test [
		Just _b ~=? contenido b_4 (dameTablero (mover (M a_3 TR) jInicial)),
		Nothing ~=? contenido a_3 (dameTablero (mover (M a_3 TR) jInicial)),
		False ~=? esNothing juego2,
		Just _b ~=? contenido d_6 (dameTablero juego2),
		Nothing ~=? contenido c_5 (dameTablero juego2),
		True ~=? esNothing (mover (M a_3 BR) jInicial),
		True ~=? esNothing juego3,
		Just _B ~=? contenido f_8 (dameTablero (mover (M e_7 TR) juego4)),
		True ~=? esNothing ((mover (M e_7 TR) juego5)),
		Just _n ~=? contenido b_8 (dameTablero (mover (M e_7 TR) juego4)),
		Just _N ~=? contenido g_1 (dameTablero (mover (M h_2 BL) juego5))
	]

tablero6 = poner b_2 _n (poner a_1 _b vacio)
juego6 = (J Blanca tablero6)

--Habria que definir una igualdad entre Juego (Eq )
testsMovimientosPosibles = test [
	[((M a_1 TR), fromJust (mover (M a_1 TR) juego6 ))] ~=?  movimientosPosibles juego6
	]

testsCantidadDeFichas = test [
	(0,0,0,0) ~=? cantidadDeFichas vacio,
	(12,0,12,0) ~=? cantidadDeFichas tableroInicial,
	(1,2,2,1) ~=? cantidadDeFichas (poner f_6 _N (poner e_5 _n (poner d_4 _n (poner c_3 _B (poner b_2 _B (poner a_1 _b vacio))))))
	]

 --testMejorMovimiento
tablero7 = poner e_6 _n (poner f_5 _B vacio)
tablero8 = poner e_4 _b $  poner h_5 _n $ poner c_8 _n tablero7
tablero9 = poner f_5 _b $ poner f_7 _n $ tablero8

mejorMovAux::Int->Color->Tablero->Movimiento
mejorMovAux nivel color tab = mejorMovimiento valuacionDamas (podar nivel (arbolDeJugadas (J color tab)))
  --nivel= las jugadas adelante que ve

testsMejorMovimiento = test [
	M f_5 TL ~=? mejorMovAux 1 Blanca tablero8,
	--captura pq solo ve 1 jugada adelante
	M f_5 TR ~=? mejorMovAux 2 Blanca tablero8,
	--la reina escapa pq no conviene el cambio
	M f_5 TR ~=? mejorMovAux 3 Blanca tablero9
	--conviene avanzar y atrapar a la _n de f_7
	]

testsTriviales = test [
	1 ~=? 1,
	2 ~=? 2,
	[1,2] ~=? [1,2],
	[1,2] ~~? [2,1]
	]

-- idem ~=? pero sin importar el orden
(~~?) :: (Ord a, Eq a, Show a) => [a] -> [a] -> Test
expected ~~? actual = (sort expected) ~=? (sort actual)
	where
		sort = foldl (\r e -> push r e) []
		push r e = (filter (e<=) r) ++ [e] ++ (filter (e>) r)

(~~) :: (Ord a, Eq a, Show a) => [a] -> [a] -> Bool
expected ~~ actual = (sort expected) == (sort actual)
	where
		sort = foldl (\r e -> push r e) []
		push r e = (filter (e<=) r) ++ [e] ++ (filter (e>) r)

-- constantes para que los tests sean más legibles		
_n = Simple Negra
_N = Reina Negra
_b = Simple Blanca
_B = Reina Blanca
a_1 = ('a',1::Int)
b_1 = ('b',1::Int)
c_1 = ('c',1::Int)
d_1 = ('d',1::Int)
e_1 = ('e',1::Int)
f_1 = ('f',1::Int)
g_1 = ('g',1::Int)
h_1 = ('h',1::Int)

a_2 = ('a',2::Int)
b_2 = ('b',2::Int)
c_2 = ('c',2::Int)
d_2 = ('d',2::Int)
e_2 = ('e',2::Int)
f_2 = ('f',2::Int)
g_2 = ('g',2::Int)
h_2 = ('h',2::Int)

a_3 = ('a',3::Int)
b_3 = ('b',3::Int)
c_3 = ('c',3::Int)
d_3 = ('d',3::Int)
e_3 = ('e',3::Int)
f_3 = ('f',3::Int)
g_3 = ('g',3::Int)
h_3 = ('h',3::Int)

a_4 = ('a',4::Int)
b_4 = ('b',4::Int)
c_4 = ('c',4::Int)
d_4 = ('d',4::Int)
e_4 = ('e',4::Int)
f_4 = ('f',4::Int)
g_4 = ('g',4::Int)
h_4 = ('h',4::Int)

a_5 = ('a',5::Int)
b_5 = ('b',5::Int)
c_5 = ('c',5::Int)
d_5 = ('d',5::Int)
e_5 = ('e',5::Int)
f_5 = ('f',5::Int)
g_5 = ('g',5::Int)
h_5 = ('h',5::Int)

a_6 = ('a',6::Int)
b_6 = ('b',6::Int)
c_6 = ('c',6::Int)
d_6 = ('d',6::Int)
e_6 = ('e',6::Int)
f_6 = ('f',6::Int)
g_6 = ('g',6::Int)
h_6 = ('h',6::Int)

a_7 = ('a',7::Int)
b_7 = ('b',7::Int)
c_7 = ('c',7::Int)
d_7 = ('d',7::Int)
e_7 = ('e',7::Int)
f_7 = ('f',7::Int)
g_7 = ('g',7::Int)
h_7 = ('h',7::Int)

a_8 = ('a',8::Int)
b_8 = ('b',8::Int)
c_8 = ('c',8::Int)
d_8 = ('d',8::Int)
e_8 = ('e',8::Int)
f_8 = ('f',8::Int)
g_8 = ('g',8::Int)
h_8 = ('h',8::Int)
